Capture app context in analytics for every command run inside an app#7771
Draft
nelsonwittwer wants to merge 4 commits into
Draft
Capture app context in analytics for every command run inside an app#7771nelsonwittwer wants to merge 4 commits into
nelsonwittwer wants to merge 4 commits into
Conversation
…mand Today only commands that load an app (app dev/deploy/...) populate api_key and project_type in Monorail; lightweight commands (search, fetch-doc, version, ...) emit nothing, so there's no way to know what app context they ran in. Enrich the global public_command_metadata hook so that — for users who are ALREADY authenticated and inside an app project — it reads the app from disk and attaches api_key + project_type. It is strictly best-effort: - gated on an existing local session; never triggers a login or any network call - short-circuits when api_key is already set (an app command already loaded the app) - threads skipPrompts through localAppContext so it can never prompt - bounded by a 3s timeout so it can't delay command exit - swallows all errors (not an app dir, invalid config, etc.) Adds a passive, non-interactive `sessionExists()` to @shopify/cli-kit/node/session. No Monorail schema change: api_key/project_type already exist on the event. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
nelsonwittwer
commented
Jun 9, 2026
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 10, 2026
The public_command_metadata hook now captures the complete app-context analytics block (api_key, project_type, app_*, cmd_app_linked_config_*, cmd_app_all_configs_*, and the sensitive app_name) when an app resolves, persists it as the most-recently-used app, and replays the whole block for commands run outside any app directory. A new public field, cmd_app_context_source, records how the context was resolved: "current_directory" for a real on-disk load, "last_used" when it was replayed from the most-recently-used app. Note: the Monorail backend schema registry must register this field for it to be retained/queryable. The snapshot keeps app identity/shape fields and excludes per-run flags (e.g. cmd_app_warning_*). Enrichment remains best-effort: authenticated users only, no prompts, no network, bounded by a short timeout, all errors swallowed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reverts the most-recently-used app replay. We no longer deduce an app for commands run outside an app directory. Instead we trust in-app context: any command run within an app path broadcasts the same app-context block a `shopify app *` command would (api_key, project_type, app_*, cmd_app_linked_config_*, and the sensitive app_name), driven by loading the app from the current directory in the public_command_metadata hook. Removes the dedicated MRU LocalStorage store, the cmd_app_context_source Monorail discriminator, and the snapshot/replay helpers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Differences in type declarationsWe detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:
New type declarationsWe found no new type declarations in this PR Existing type declarationspackages/cli-kit/dist/public/node/session.d.ts@@ -47,6 +47,22 @@ export declare function isUserAccount(account: AccountInfo): account is UserAcco
* @returns True if the account is a ServiceAccount.
*/
export declare function isServiceAccount(account: AccountInfo): account is ServiceAccountInfo;
+/**
+ * Reports whether the CLI already has stored credentials, without prompting the
+ * user, opening a browser, or making any network request.
+ *
+ * This is a passive, side-effect-free check: it reads the local session store and
+ * returns when at least one valid session is present. Unlike the
+ * functions, it never triggers a login flow and never logs
+ * the user out. Because it does not contact the network, it cannot tell whether the
+ * stored token is currently valid/unexpired — only that credentials exist locally.
+ *
+ * Intended for best-effort, opportunistic behaviour (for example, enriching
+ * telemetry only for users who are already logged in).
+ *
+ * @returns True if local credentials exist, false otherwise.
+ */
+export declare function sessionExists(): Promise<boolean>;
/**
* Ensure that we have a valid session with no particular scopes.
*
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Makes command analytics capture app context for every CLI command run inside an app — not just commands that explicitly load an app.
Why
App-level telemetry is already flowing, but only as a side effect of commands that authenticate and load an app.
Commands that don't load an app (
search,fetch-doc,version,upgrade, …) emit nothing, so we can't tell what app context they were run in. We need this signal everywhere so we can judge the effectiveness of commands, especially when run by agents in different harnesses/models.How
The
public_command_metadatahook runs on the postrun of every command. It now calls a best-effort helper,logAppContextMetadataIfAuthenticated(cwd()), which — only when the user is already authenticated and is inside an app project — loads the app from the current directory and broadcasts the same app-context block ashopify app *command would (api_key,project_type, theapp_*fields,cmd_app_linked_config_*, and the sensitiveapp_name).We do not deduce an app for commands run outside an app directory. The behavior is simply: if the command is run within the path of an app, it broadcasts that app's context; otherwise it broadcasts nothing app-related.
It is strictly best-effort and safe to run everywhere:
sessionExists()) — never triggers a login, never makes a network request. Anonymous/CI usage stays unenriched.api_keyis already set — app commands already populated it, so there's no redundant work.skipPromptsis threaded throughlocalAppContext→getAppConfigurationContext.🎩 testing instructions